package com.suray.wcs.web.system.controller;

import com.suray.basic.wcs.plc.utils.PlcDeviceProcess;
import com.suray.basic.wcs.utils.Coord;
import com.suray.commin.annotation.Log;
import com.suray.commin.core.controller.BaseController;
import com.suray.commin.core.page.TableDataInfo;
import com.suray.commin.core.utils.SecurityUtils;
import com.suray.commin.core.utils.StringUtils;
import com.suray.commin.enmus.BusinessType;
import com.suray.commin.core.controller.ResponseData;
import com.suray.commin.enmus.DeviceStatus;
import com.suray.wcs.service.init.SystemInit;
import com.suray.wcs.service.system.entity.NodeDB;
import com.suray.basic.wcs.plc.entity.PlcDeviceDB;
import com.suray.wcs.service.system.entity.ProgrammeDB;
import com.suray.wcs.service.system.service.impl.NodeDBServiceImpl;
import com.suray.basic.wcs.plc.service.impl.PlcDeviceDBServiceImpl;
import com.suray.wcs.service.system.service.impl.PortDBServiceImpl;
import com.suray.wcs.service.system.service.impl.ProgrammeServiceImpl;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.beanutils.ConvertUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @Description:方案配置前端控制器
 * @author: rongbj
 * @date:2019年12月5日 上午9:55:14
 */
@RestController
@RequestMapping("/programme")
@CrossOrigin
public class ProgrammeDBController extends BaseController {
    @Autowired
    private ProgrammeServiceImpl programmeService;
    @Autowired
    private NodeDBServiceImpl nodedbServiceImpl;
    @Autowired
    private PortDBServiceImpl portDBService;
    @Autowired
    private PlcDeviceDBServiceImpl plcDeviceDBService;

    private Logger log = LoggerFactory.getLogger(ProgrammeDBController.class);


    /**
     * 获取出入库口
     *
     * @return
     */
    @ApiOperation("获取出入库口")
    @GetMapping("/getPorts")
    public ResponseData getPorts() {
        return ResponseData.success(portDBService.list());
    }

    /**
     * 获取PLC设备 (工位和提升机)
     *
     * @return
     */
    @ApiOperation("获取PLC设备")
    @GetMapping("/getPlcDevices")
    public ResponseData getPlcDevices() {
        return ResponseData.success(plcDeviceDBService.queryPlcDevices());
    }

    /**
     * 获取PLC设备 (工位和提升机)
     *
     * @return
     */
    @ApiOperation("获取PLC设备")
    @GetMapping("/getPlcConvDevices")
    public ResponseData getPlcConvDevices() {
        return ResponseData.success(plcDeviceDBService.queryPlcConvDevices());
    }

    /**
     * 获取接驳点
     *
     * @return
     */
    @ApiOperation("获取接驳点")
    @GetMapping("/connectCoord")
    public ResponseData getConnectCoord() {
        List<Coord> coordList = new ArrayList<>();
        for (NodeDB portCrood : nodedbServiceImpl.getNodeDBByType()) {
            coordList.add(new Coord(portCrood.getGridx(), portCrood.getGridy(), portCrood.getGridz()));
        }
        return ResponseData.success(coordList);
    }


    /**
     * 查询库口配置
     *
     * @param programmeDB
     * @return
     */
    @PreAuthorize("@ss.hasPermi('programme:list')")
    @ApiOperation("查询库口配置")
    @GetMapping(value = "/list")
    public TableDataInfo queryProgrammeConf(ProgrammeDB programmeDB) {
        startPage();
        List<ProgrammeDB> result = programmeService.queryProgrammeConf(programmeDB);
        for (ProgrammeDB db : result) {
            StringBuffer programmeStr = new StringBuffer();
            if (StringUtils.isNotEmpty(db.getProgramme())) {
                for (String param : db.getProgramme().split("-")) {
                    PlcDeviceProcess deviceProcess = PlcDeviceProcess.parseDeviceProcess(Integer.valueOf(param));
                    switch (deviceProcess) {
                        case INVALID:
                            //设备ID，不处理
                            break;
                        case CALL_RGV:
                        case LOCK_HAVE_CARGO:
                        case LOCK_NO_CARGO:
                        case UNLOCK:
                        case FORWARD_TRANS_CARGO:
                        case BACK_TRANS_CARGO:
                        case TRANS_PLANTER_UP:
                        case TRANS_PLANTER_DOWN:
                            programmeStr.append(deviceProcess.getDes() + "->");
                            break;
                        default:
                            programmeStr.append(param + ":未知方案->");
                            break;
                    }

                    if (deviceProcess != PlcDeviceProcess.INVALID) {
                        continue;
                    }

                    PlcDeviceDB plcdeviceDB = plcDeviceDBService.selectPlcDevById(Long.parseLong(param));
                    if (plcdeviceDB == null) {
                        programmeStr.append(param + ":未知方案->");
                    } else {
                        programmeStr.append(plcdeviceDB.getDeviceName() + "->");
                    }
                }
            }
            if (StringUtils.isNotEmpty(programmeStr)) {
                db.setProgrammeStr(programmeStr.delete(programmeStr.lastIndexOf("-"), programmeStr.length()).toString());
            }
        }
        return getDataTable(result);
    }

    /**
     * 状态修改
     */
    @PreAuthorize("@ss.hasPermi('programme:edit')")
    @ApiOperation("方案状态修改")
    @Log(title = "方案配置", method = "方案状态修改", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public ResponseData changeStatus(@RequestBody ProgrammeDB programmeDB) {
        programmeDB.setUpdateBy(SecurityUtils.getUsername());
        if (programmeService.updateProgrammeStatus(programmeDB) > 0) {
            SystemInit.initProgrammeMap();
            return ResponseData.success();
        } else {
            return ResponseData.error("方案状态修改失败");
        }
    }


    /**
     * 获取方案
     */
    @ApiOperation("获取方案")
    @GetMapping(value = "/{programmeId}")
    public ResponseData getInfo(@PathVariable Long programmeId) {
        ProgrammeDB programmeDB = programmeService.selectByProgrammeId(programmeId);
        if (programmeDB.getCoords() != null) {
            programmeDB.setConnectCoord(programmeDB.getCoords().split(";"));
        }
        if (StringUtils.isNotEmpty(programmeDB.getProgramme())) {
            programmeDB.setPlcDeviceIds((Long[]) ConvertUtils.convert(programmeDB.getProgramme().split("-"), Long.class));
        }
        return ResponseData.success(programmeDB);
    }

    /**
     * 新增方案
     *
     * @param programmeDB
     * @return
     */
    @PreAuthorize("@ss.hasPermi('programme:add')")
    @Log(title = "方案配置", method = "新增方案", businessType = BusinessType.INSERT)
    @ApiOperation("新增方案")
    @PostMapping(value = "/addProgramme")
    public ResponseData addProgramme(@Validated @RequestBody ProgrammeDB programmeDB) {
        programmeDB.setCreateBy(SecurityUtils.getUsername());
        if (programmeDB.getPlcDeviceIds() != null) {
            StringBuffer programmeStr = new StringBuffer();
            for (int i = 0; i < programmeDB.getPlcDeviceIds().length; i++) {
                Long plcDeviceId = programmeDB.getPlcDeviceIds()[i];
                programmeStr.append(plcDeviceId + "-");
            }

            if (StringUtils.isNotEmpty(programmeStr)) {
                programmeDB.setProgramme(programmeStr.delete(programmeStr.lastIndexOf("-"), programmeStr.length()).toString());
            }
        }
        if (programmeDB.getConnectCoord() != null) {
            StringBuffer coords = new StringBuffer();
            for (int i = 0; i < programmeDB.getConnectCoord().length; i++) {
                String connect = programmeDB.getConnectCoord()[i];
                coords.append(connect + ";");
            }
            programmeDB.setCoords(coords.toString());
        }
        programmeDB.setCreateTime(new Date());
        if (programmeService.save(programmeDB)) {
            SystemInit.initProgrammeMap();
            return ResponseData.success();
        } else {
            return ResponseData.error("新增方案失败");
        }
    }

    /**
     * 方案删除
     */
    @PreAuthorize("@ss.hasPermi('programme:remove')")
    @ApiOperation("方案删除")
    @Log(title = "方案配置", method = "方案删除", businessType = BusinessType.DELETE)
    @DeleteMapping(value = "delProgramme/{programmeIds}")
    public ResponseData getInfo(@PathVariable Long[] programmeIds) {
        for (Long programmeId : programmeIds) {
            ProgrammeDB byId = programmeService.getById(programmeId);
            if (byId.getStatus().equals(DeviceStatus.OK.getCode())) {
                return ResponseData.error("方案:" + byId.getProgrammeName() + "启用中不允许删除！");
            }
        }
        if (programmeService.removeByIds(Arrays.asList(programmeIds))) {
            SystemInit.initProgrammeMap();
            return ResponseData.success();
        } else {
            return ResponseData.error("方案删除失败");
        }
    }

    /**
     * 修改方案
     */
    @PreAuthorize("@ss.hasPermi('programme:edit')")
    @Log(title = "方案配置", method = "修改方案", businessType = BusinessType.UPDATE)
    @ApiOperation("修改方案")
    @PutMapping("/updateProgramme")
    public ResponseData updateProgramme(@Validated @RequestBody ProgrammeDB programmeDB) {
        programmeDB.setUpdateBy(SecurityUtils.getUsername());
        if (programmeDB.getPlcDeviceIds() != null && programmeDB.getPlcDeviceIds().length != 0) {
            StringBuffer programmeStr = new StringBuffer();
            for (int i = 0; i < programmeDB.getPlcDeviceIds().length; i++) {
                Long plcDeviceId = programmeDB.getPlcDeviceIds()[i];
                programmeStr.append(plcDeviceId + "-");
            }

            if (StringUtils.isNotEmpty(programmeStr)) {
                programmeDB.setProgramme(programmeStr.delete(programmeStr.lastIndexOf("-"), programmeStr.length()).toString());
            }
        } else {
            programmeDB.setProgramme("");
        }
        if (programmeDB.getConnectCoord() != null) {
            StringBuffer coords = new StringBuffer();
            for (int i = 0; i < programmeDB.getConnectCoord().length; i++) {
                String connect = programmeDB.getConnectCoord()[i];
                coords.append(connect + ";");
            }
            programmeDB.setCoords(coords.toString());
        }
        boolean result = programmeService.updateById(programmeDB);
        if (result) {
            SystemInit.initProgrammeMap();
        }
        return toAjax(result);
    }

}
